package com.blogs.component;

import com.blogs.ui.ImageShowActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

	private SurfaceHolder sfh;
	private Bitmap bmp;
	private Object lockObj = new Object();
	private Paint mPaint = new Paint();

	private GestureDetector mGesture;

	private Rect imgScr;// 图片边界
	private RectF bmBounds, tmpBounds;// 屏幕边界

	private static int MODE_NONE = 0;
	private static int MODE_DRAG = 1;
	private static int MODE_ZOOM = 2;
	private int mode = MODE_NONE;

	private PointF startPoint = new PointF();
	private boolean stopInertia;
	private float oldDist;
	private float maxScale = 15f;
	private PointF CimgP;

	// private ImageStateChangedListener stateChangedListener;
	public MySurfaceView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
		// TODO Auto-generated constructor stub
	}

	public MySurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
		// TODO Auto-generated constructor stub
	}

	public MySurfaceView(Context context, Bitmap bitmap) {
		super(context);
		// this.bmp = bitmap;
		init();
	}

	public MySurfaceView(Context context) {
		super(context);
		init();
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// TODO Auto-generated method stub

	}

	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		getHolder().setFormat(PixelFormat.TRANSPARENT);
		try
		{
			this.initImage();
		}
		catch (Exception e) {
			// TODO: handle exception
		}

	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub

	}

	private void init() {
		sfh = this.getHolder();// 获取holder对象
		sfh.setFormat(PixelFormat.TRANSPARENT);
		sfh.addCallback(this);// 添加surface回调函数

		mPaint.setAntiAlias(true);
		mPaint.setFilterBitmap(true);

		mGesture = new GestureDetector(getContext(), new MySimpleGestureListener());
	}

	private void initImage() {
		// 初始化图像
		Log.i("sfbmp", bmp==null?"ture":"false");
		Log.i("surfaceView",
				"w:" + getWidth() + ",h:" + getHeight() + ",bw:" + bmp.getWidth() + ",wh:" + bmp.getHeight());
		float iLeft;// 图片左边的距离
		float iTop;// 图片顶部的距离
		float iHeight;// 图片高度
		float iWidth;// 图片宽度

		imgScr = new Rect();
		bmBounds = new RectF();

		imgScr.set(0, 0, bmp.getWidth(), bmp.getHeight());
		if ((float) bmp.getWidth() / (float) bmp.getHeight() >= (float) this.getMeasuredWidth()
				/ (float) this.getMeasuredHeight()) {
			iWidth = this.getMeasuredWidth();// 初始图片宽度
			iHeight = ((float) bmp.getHeight() / (float) bmp.getWidth()) * this.getMeasuredWidth();// 初始图片高度
			iLeft = 0;
			iTop = Math.abs((this.getMeasuredHeight() - iHeight) / 2.0f);
			bmBounds.set(iLeft, iTop, iLeft + iWidth, iTop + iHeight);
		} else {
			iWidth = ((float) bmp.getWidth() / (float) bmp.getHeight()) * this.getMeasuredHeight();// 初始图片宽度
			iHeight = this.getMeasuredHeight();// 初始图片高度
			iLeft = Math.abs((this.getMeasuredWidth() - iWidth) / 2.0f);
			iTop = 0;
			bmBounds.set(iLeft, iTop, iLeft + iWidth, iTop + iHeight);
		}

		tmpBounds = new RectF(bmBounds);
		this.drawImage(bmp);

		// /*使用矩阵变换*/
		// Matrix matrix = new Matrix();
		// int bmpWidth = bmp.getWidth();
		// int bmpHeight = bmp.getHeight();
		// Log.i("bmpwh",
		// bmpWidth+","+bmpHeight+","+this.iWidth+","+this.iHeight);
		// matrix.postScale((float)this.iWidth / bmpWidth,(float) this.iHeight /
		// bmpHeight);
		// this.drawImage(Bitmap.createBitmap(bmp, 0, 0,bmpWidth, bmpHeight,
		// matrix, true));
		// /*使用矩阵变换*/

	}

	class MySimpleGestureListener extends SimpleOnGestureListener {
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			// if (stateChangedListener != null) {
			// stateChangedListener.onDoubleClick();
			// }
			return super.onDoubleTap(e);
		}

		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
			return true;
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			if (Math.abs(velocityX) > 60 && Math.abs(velocityY) > 60) {
				float dx = Math.abs(e2.getX() - e1.getX());
				float dy = Math.abs(e2.getY() - e1.getY());
				if (dx >= dy) {
					inertiaX(e1, e2, velocityX);
				} else {
					inertiaY(e1, e2, velocityY);
				}
			}
			return false;
		}
	}

	public void setImage(Bitmap bitmap) {
		if (bitmap != null && !bitmap.isRecycled() && bitmap.getWidth() > 0 && bitmap.getHeight() > 0) {
			this.bmp = bitmap;

		}
	}

	public void drawImage(Bitmap bitmap) {
		try {
			synchronized (lockObj) {
				Canvas canvas = sfh.lockCanvas();

				if (canvas != null && bitmap != null) {
					canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
					canvas.drawColor(0x00000000);

					// canvas.drawBitmap(bitmap, this.iLeft, this.iTop, mPaint);
					canvas.drawBitmap(bitmap, imgScr, bmBounds, mPaint);

					sfh.unlockCanvasAndPost(canvas);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			mode = MODE_DRAG;
			stopInertia = true;
			startPoint.set(event.getX(), event.getY());
			if (this.getContext() instanceof ImageShowActivity) {

				((ImageShowActivity) this.getContext()).actionDown();
			}
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			stopInertia = true;
			oldDist = spacing(event);
			CimgP = midPoint(event);
			if (oldDist > 10f) {
				mode = MODE_ZOOM;
			}
			break;
		case MotionEvent.ACTION_UP:
		case MotionEvent.ACTION_POINTER_UP:
			// stopInertia = true;
			mode = MODE_NONE;
			break;
		case MotionEvent.ACTION_MOVE:
			if (mode == MODE_DRAG) {
				float dx = event.getX() - startPoint.x;
				float dy = event.getY() - startPoint.y;
				bmBounds.offset(dx, dy);
				isOverBounds();
				drawImage(bmp);
				startPoint.set(event.getX(), event.getY());
			} else if (mode == MODE_ZOOM) {
				float newDist = spacing(event);
				float scale = newDist / oldDist;
				zoom(scale, CimgP);
				oldDist = newDist;
			}
			break;
		}
		return mGesture.onTouchEvent(event);
	}

	/*
	 * 求两点间距离
	 */
	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}

	/*
	 * 求两点间的中点
	 */
	private PointF midPoint(MotionEvent event) {
		PointF p = new PointF();
		p.x = (event.getX(0) + event.getX(1)) / 2f;
		p.y = (event.getY(0) + event.getY(1)) / 2f;
		return p;
	}

	private void zoom(float scale, PointF mpoint) {
		if (bmBounds == null)
			return;
		float newWidth = scale * bmBounds.width();
		float newHeight = scale * bmBounds.height();
		float lx = (newWidth - bmBounds.width()) / 2f;
		float ly = (newHeight - bmBounds.height()) / 2f;
		if (newWidth / tmpBounds.width() > maxScale) {
			lx = (maxScale * tmpBounds.width() - bmBounds.width()) / 2f;
			ly = (maxScale * tmpBounds.height() - bmBounds.height()) / 2f;
		} else if (newWidth < tmpBounds.width()) {
			lx = (tmpBounds.width() - bmBounds.width()) / 2f;
			ly = (tmpBounds.height() - bmBounds.height()) / 2f;
		}
		bmBounds.inset(-lx, -ly);
		PointF imgMPoint = new PointF();// 图片中点位置
		imgMPoint.x = (bmBounds.left + bmBounds.right) / 2f;
		imgMPoint.y = (bmBounds.top + bmBounds.bottom) / 2f;
		float dx = -(mpoint.x - imgMPoint.x) * (scale - 1);
		float dy = -(mpoint.y - imgMPoint.y) * (scale - 1);
		// bmBounds.inset(dx, dy);
		drawImage(bmp);
	}

	private void zoom(float scale) {
		if (bmBounds == null)
			return;
		float newWidth = scale * bmBounds.width();
		float newHeight = scale * bmBounds.height();
		float lx = (newWidth - bmBounds.width()) / 2f;
		float ly = (newHeight - bmBounds.height()) / 2f;
		if (newWidth / tmpBounds.width() > maxScale) {
			lx = (maxScale * tmpBounds.width() - bmBounds.width()) / 2f;
			ly = (maxScale * tmpBounds.height() - bmBounds.height()) / 2f;
		} else if (newWidth < tmpBounds.width()) {
			lx = (tmpBounds.width() - bmBounds.width()) / 2f;
			ly = (tmpBounds.height() - bmBounds.height()) / 2f;
		}
		bmBounds.inset(-lx, -ly);
		isOverBounds();
		drawImage(bmp);
	}

	/**
	 * 缩小
	 */
	public void zoomOut() {
		float scale = 0.8f;
		zoom(scale);
	}

	/**
	 * 放大
	 */
	public void zoomIn() {
		float scale = 1.2f;
		zoom(scale);
	}

	private boolean isOverBounds() {

		boolean isOver = false;
		float dx = 0;
		float dy = 0;
		if ((float) bmp.getWidth() / (float) bmp.getHeight() >= (float) this.getMeasuredWidth()
				/ (float) this.getMeasuredHeight()) {
			if (bmBounds.left > 0) {
				dx = -bmBounds.left;
				isOver = true;
			} else if (bmBounds.right < getMeasuredWidth()) {
				dx = getMeasuredWidth() - bmBounds.right;
				isOver = true;
			}
			float top = 0;
			float bottom = getMeasuredHeight();
			if (bmBounds.height() < getMeasuredHeight()) {
				top = (getMeasuredHeight() - bmBounds.height()) / 2f;
				bottom = top + bmBounds.height();
			}
			if (bmBounds.top > top) {
				dy = top - bmBounds.top;
				isOver = true;
			} else if (bmBounds.bottom < bottom) {
				dy = bottom - bmBounds.bottom;
				isOver = true;
			}
		} else {
			if (bmBounds.top > 0) {
				dy = -bmBounds.top;
				isOver = true;
			} else if (bmBounds.bottom < getMeasuredHeight()) {
				dy = getMeasuredHeight() - bmBounds.bottom;
				isOver = true;
			}

			float left = 0;
			float right = getMeasuredWidth();
			if (bmBounds.width() < getMeasuredWidth()) {
				left = (getMeasuredWidth() - bmBounds.width()) / 2f;
				right = left + bmBounds.width();
			}
			if (bmBounds.left > left) {
				dx = left - bmBounds.left;
				isOver = true;
			} else if (bmBounds.right < right) {
				dx = right - bmBounds.right;
				isOver = true;
			}
		}
		bmBounds.offset(dx, dy);
		return isOver;
	}

	private int velocity = 20;
	private float g = 0.98f;
	private float vxt = 0;
	private float t;
	private float vyt = 0;

	// X轴上的惯性移动
	private void inertiaX(MotionEvent e1, MotionEvent e2, final float velocityX) {
		final float vx = velocityX / velocity;
		Log.i("velocityX", vx + "");
		t = 0;
		new Thread() {
			@Override
			public void run() {
				super.run();
				do {
					vxt = Math.abs(vx) - t * g;
					t++;
					if (vx < 0)
						bmBounds.offset(-vxt, 0);
					else
						bmBounds.offset(vxt, 0);
					boolean isOver = isOverBounds();
					drawImage(bmp);
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (isOver)
						break;
				} while (vxt > 0 && !stopInertia);
			}
		}.start();
	}

	// Y轴上的惯性移动
	private void inertiaY(MotionEvent e1, MotionEvent e2, float velocityY) {
		final float vy = velocityY / velocity;
		t = 0;
		Log.i("velocityY", vy + "");
		new Thread() {
			@Override
			public void run() {
				super.run();
				do {
					vyt = Math.abs(vy) - t * g;
					t++;
					if (vy < 0)
						bmBounds.offset(0, -vyt);
					else
						bmBounds.offset(0, vyt);
					boolean isOver = isOverBounds();
					drawImage(bmp);
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					if (isOver)
						break;
				} while (vyt > 0 && !stopInertia);
			}
		}.start();
	}

}
